package com.tuling.echo.pool;

import java.util.LinkedList;

/**
 * 自定义线程池的实现
 * https://www.cnblogs.com/gosaint/p/8494423.html
 *
 * @author: chenhs
 * @date: Created in 10:40 2022/10/28
 **/
public class ThreadPool extends ThreadGroup {
    private boolean isClosed = false;//线程池是否关闭
    private LinkedList<Runnable> workQuee;//表示工作队列
    private static int threadPoolID;//表示线程池ID
    private int workThreadID;//表示工作线程池ID

    public ThreadPool(int poolSize) {
        //poolSize表示线程池中工作线程的数目
        //每一次的初始化，线程池ID都会自动增加
        super("ThreadPool-" + (threadPoolID++));
        //设置为守护线程
        setDaemon(true);
        workQuee = new LinkedList<>();//创建工作队列
        for (int i = 0; i < poolSize; i++) {
            new WorkThread().start();
        }
    }

    /**
     * 向工作队列中添加一个新的任务，让工作线程去执行
     *
     * @param task
     */
    public synchronized void execute(Runnable task) {
        if (isClosed) {
            //线程池关闭，则抛出如下的异常
            throw new IllegalStateException();
        }
        if (task != null) {
            workQuee.add(task);
            notify();//唤醒正在等待获取任务的工作线程getTask();
        }
    }

    /**
     * 从工作队列中取出一个线程，让线程执行任务
     *
     * @return
     * @throws InterruptedException
     */
    public synchronized Runnable getTask() throws InterruptedException {
        while (workQuee.size() == 0) {
            //当工作队列中的线程为0时，如果线程池关闭，则返回null.负责，等待任务
            if (isClosed) {
                return null;
            } else {
                wait();
            }
        }
        return workQuee.removeFirst();//从工作队列中弹出第一个元素
    }

    /**
     * 关闭线程池
     */
    public synchronized void closed() {
        //线程池没有关闭
        if (!isClosed) {
            isClosed = true;
            workQuee.clear();//清除工作队列
            interrupt();//中断所有的线程
        }
    }

    /**
     * 等在工作线程将若有的任务执行完毕
     */
    public void join() {
        synchronized (this) {
            isClosed = true;
            notifyAll();//唤醒所有的等待任务的工作线程
        }
        //activeCount() 返回此线程组中活动线程的估计数。 来自ThreadGroup
        Thread[] threads = new Thread[activeCount()];
        // enumerate[list] 把此线程组及其子组中的所有活动线程复制到指定数组中。
        int count = enumerate(threads);//返回所有的活着的线程数量
        for (int i = 0; i < count; i++) {
            try {
                threads[i].join();//等待所有的活动的工作宣称的结束
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 内部类，创建的工作线程对象
     */
    private class WorkThread extends Thread {
        public WorkThread() {
            super(ThreadPool.this, "WorkThread-" + workThreadID++);
        }

        @Override
        public void run() {
            //线程没有中断
            while (!isInterrupted()) {
                Runnable task = null;
                try {
                    task = getTask();//获取任务
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (task == null) {
                    return;
                }
                try {
                    task.run();//运行任务
                } catch (Throwable t) {
                    t.printStackTrace();
                }

            }
        }
    }

}
